package top.aicey.ai.sparring.controller;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;

import lombok.extern.slf4j.Slf4j;
import top.aicey.ai.sparring.common.constants.AIConstants;
import top.aicey.ai.sparring.common.constants.AIErrorConstants;
import top.aicey.ai.sparring.common.holder.SparringContext;
import top.aicey.ai.sparring.common.utils.BaseResponseUtil;
import top.aicey.ai.sparring.dto.enums.RoleEnum;
import top.aicey.ai.sparring.dto.enums.SparringStatusEnum;
import top.aicey.ai.sparring.dto.model.BaseResponse;
import top.aicey.ai.sparring.dto.req.CallLogRequestDto;
import top.aicey.ai.sparring.dto.res.QuestionAnswerPairsResponse;
import top.aicey.ai.sparring.entity.SceneInstanceLog;
import top.aicey.ai.sparring.entity.SceneQaPairs;
import top.aicey.ai.sparring.listener.ReportEventPublisher;
import top.aicey.ai.sparring.processor.DefaultSparringContextProcessorExecutor;
import top.aicey.ai.sparring.processor.LogIndexContextProcessorExecutor;
import top.aicey.ai.sparring.service.DelayAIAgentInstanceService;
import top.aicey.ai.sparring.service.ISceneInstanceEvaluationService;
import top.aicey.ai.sparring.service.ISceneInstanceLogService;
import top.aicey.ai.sparring.service.ISceneQaPairsService;

@RestController
@RequestMapping("/v3/sparing/")
@Slf4j
public class AiQaSparingController {

    @Autowired
    private ISceneQaPairsService sceneQaPairsService;

    @Autowired
    private ISceneInstanceLogService sceneInstanceLogService;

    @Autowired
    private DefaultSparringContextProcessorExecutor sparringContextSelector;

    @Autowired
    private LogIndexContextProcessorExecutor logIndexContextProcessorExecutor;

    @Resource
    private DelayAIAgentInstanceService delayAIAgentInstanceService;


    @Autowired
    private ISceneInstanceEvaluationService sceneInstanceEvaluationService;

    @Autowired
    private ReportEventPublisher reportEventPublisher;



    /**
     * 根据场景查询问答对
     *
     * @param
     * @return
     * @throws Exception
     */
    @PostMapping(value = "/qa-pair")
    public BaseResponse<QuestionAnswerPairsResponse> qaPairs(@RequestParam(value = "instanceId") String instanceId) {

        SparringContext context = sparringContextSelector.get(instanceId);
        log.info("qa-pairs context:{}",context);
        if (Objects.isNull(context)){
            log.info("AI instance does not exist!instanceId:{}",instanceId);
            return BaseResponseUtil.buildFailedResponse(AIErrorConstants.AI_INSTANCE_INFO_ERROR);
        }

        if (SparringStatusEnum.ON_INIT.equals(context.getStatus())){
            String moduleId = context.getModuleId();
            Long sceneId = context.getSceneId();
            // 如果状态是刚初始化好的  则需要去数据库抓取数据
            List<SceneQaPairs> list = sceneQaPairsService.listBySceneId(moduleId,sceneId);

            if (CollectionUtils.isEmpty(list)){
                log.info("qa-pairs list is null instanceId:{}",instanceId);
                return BaseResponseUtil.buildSuccessResponse(Lists.newArrayList());
            }

            List<QuestionAnswerPairsResponse> responses = list.stream().map(v -> {
                QuestionAnswerPairsResponse response = new QuestionAnswerPairsResponse();
                response.setQuestion(v.getQuestion());
                response.setAnswer(v.getAnswer());
                response.setId(v.getId());
                return response;
            }).collect(Collectors.toList());

            log.info("qa-pairs responses:{}", JSON.toJSONString(responses));
            context.setQaList(responses);
            context.setStatus(SparringStatusEnum.IN_PROGRESS);
        }

        Integer point = context.getPoint();

        if (point + 1> context.getQaList().size()){
            // 准备发起结束流程
            QuestionAnswerPairsResponse response = new QuestionAnswerPairsResponse();
            response.setQuestion(AIConstants.AI_INSTANCE_END);
            context.setQuestionPoint(response);
            context.setStatus(SparringStatusEnum.END);
            sparringContextSelector.put(context);
            // 如果已经超出问题 返回结束语
            return BaseResponseUtil.buildSuccessResponse(response);
        }

        QuestionAnswerPairsResponse response = context.getQaList().get(point);

        // 保存下一个指针位置
        context.setPoint(context.getPoint() + 1);
        context.setQuestionPoint(response);
        sparringContextSelector.put(context);

        log.info("AI instance response!instanceId:{},response:{}",instanceId,response);
        return BaseResponseUtil.buildSuccessResponse(response);
    }


    /**
     * 记录用户输入日志
     *
     * @param
     * @return
     * @throws Exception
     */
    @PostMapping(value = "/user-input/log")
    public BaseResponse userInputLog(@RequestParam(value = "instanceId") String instanceId, @RequestBody
        CallLogRequestDto body) {

        SparringContext context = sparringContextSelector.get(instanceId);
        log.info("qa-pairs context:{}",context);
        if (Objects.isNull(context)){
            log.info("AI instance does not exist!instanceId:{}",instanceId);
            return BaseResponseUtil.buildFailedResponse(AIErrorConstants.AI_INSTANCE_INFO_ERROR);
        }

        if (AIConstants.START.equals(body.getMessage())){
            // 开始这句不记录
            return BaseResponseUtil.buildSuccessResponse();
        }

        saveInstanceLog(instanceId, body, context,RoleEnum.USER);
        return BaseResponseUtil.buildSuccessResponse();
    }

    /**
     * 记录用户输入日志
     *
     * @param
     * @return
     * @throws Exception
     */
    @PostMapping(value = "/ai-output/log")
    public BaseResponse aiOutputLog(@RequestParam(value = "instanceId") String instanceId, @RequestBody CallLogRequestDto body) {

        SparringContext context = sparringContextSelector.get(instanceId);
        log.info("qa-pairs context:{}",context);
        if (Objects.isNull(context)){
            log.info("AI instance does not exist!instanceId:{}",instanceId);
            return BaseResponseUtil.buildFailedResponse(AIErrorConstants.AI_INSTANCE_INFO_ERROR);
        }

        if (SparringStatusEnum.END.equals(context.getStatus())){
            logIndexContextProcessorExecutor.clear(instanceId);
            return BaseResponseUtil.buildSuccessResponse();
        }

        saveInstanceLog(instanceId, body, context,RoleEnum.AI);
        return BaseResponseUtil.buildSuccessResponse();
    }


    /**
     * 记录用户输入日志
     *
     * @param
     * @return
     * @throws Exception
     */
    @PostMapping(value = "/end-handle")
    public BaseResponse endHandle(@RequestParam(value = "instanceId") String instanceId) {

        SparringContext context = sparringContextSelector.get(instanceId);
        log.info("end-handle context:{}",context);
        if (Objects.isNull(context)){
            log.info("end-handle AI instance does not exist!instanceId:{}",instanceId);
            return BaseResponseUtil.buildFailedResponse(AIErrorConstants.AI_INSTANCE_INFO_ERROR);
        }

        if (SparringStatusEnum.END.equals(context.getStatus())){
            // 初始化评价
            boolean initialized = sceneInstanceEvaluationService.initBySparringContext(context);

            if (!initialized){
                // 已经存在了  则不再处理
                return BaseResponseUtil.buildSuccessResponse();
            }
            // 发起评估
            reportEventPublisher.generateReport(context);

            delayAIAgentInstanceService.delayStopAIAgentInstance(context.getAiAgentInstanceId());

            sparringContextSelector.clear(instanceId);
        }
        return BaseResponseUtil.buildSuccessResponse();
    }



    private void saveInstanceLog(String instanceId, CallLogRequestDto body, SparringContext context,RoleEnum roleEnum) {
        SceneInstanceLog sceneInstanceLog = new SceneInstanceLog();
        sceneInstanceLog.setCreatedBy(context.getUserId());
        sceneInstanceLog.setUpdatedBy(context.getUserId());
        sceneInstanceLog.setUpdatedAt(LocalDateTime.now());
        sceneInstanceLog.setCreatedAt(LocalDateTime.now());

        sceneInstanceLog.setContent(body.getMessage());
        sceneInstanceLog.setModuleId(context.getModuleId());
        sceneInstanceLog.setInstanceId(context.getInstanceId());
        sceneInstanceLog.setRole(roleEnum);
        sceneInstanceLog.setOrderId(logIndexContextProcessorExecutor.incr(instanceId));
        sceneInstanceLog.setSceneId(context.getSceneId());
        sceneInstanceLog.setQaPairId(context.getQuestionPoint().getId());
        sceneInstanceLogService.save(sceneInstanceLog);
    }





}

